package com.feilong.edgeAI.speech;

import static com.feilong.edgeAI.ui.HomeActivity.AI_MODE;
import static com.feilong.edgeAI.ui.HomeActivity.AI_TOGGLE;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.util.Log;

import com.alibaba.android.arouter.utils.TextUtils;
import com.blankj.utilcode.util.SPUtils;
import com.feilong.edgeAI.SpeechApp;
import com.feilong.edgeAI.speech.util.AbilityConstant;
import com.iflytek.aikit.core.AiEvent;
import com.iflytek.aikit.core.AiHandle;
import com.iflytek.aikit.core.AiHelper;
import com.iflytek.aikit.core.AiListener;
import com.iflytek.aikit.core.AiRequest;
import com.iflytek.aikit.core.AiResponse;
import com.iflytek.aikit.core.AiText;

import java.util.List;

/**
 * Created by【仿脑科技】
 *
 * @Author: potato
 * @CreateDate: 2023/11/23 9:50
 */
public class TTSHelper implements AiListener {
    public static final int ONLINE_AI = 1;
    public static final int OFFLINE_AI = 2;
    private static final String TAG = "feilongedgeAI";
    public static int eventType;
    private static int sampleRateInHz = 16000;
    private static int channelConfig = AudioFormat.CHANNEL_OUT_MONO;
    private static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
    private static int bufferSizeInBytes = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
    //语音合成文件缓存数组
    private static byte[] cacheArray;
    private static AiHandle aiHandle;
    //播放组件
    private static AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes, AudioTrack.MODE_STREAM);

    public TTSHelper() {
//        pcmAudioPlayer.
        AiHelper.getInst().registerListener(AbilityConstant.XTTS_ID, this);
        int ret = AiHelper.getInst().engineInit(AbilityConstant.XTTS_ID);
        if (ret != AbilityConstant.ABILITY_SUCCESS_CODE) {
            Log.w(TAG, "open TTSHelper error code ===> $ret");
        }
    }
    public static final int STAND_SPEED=50;
    private String voiceName = "xiaoyan";
    private int language = 1;
    private int volume = 100;
    private int speed = STAND_SPEED;
    private boolean interrupted;
    public void setVoiceName(String name) {
        voiceName = name;
    }

    public void setLanguage(int language) {
        this.language = language;
    }

    public void setVolume(int volume) {
        this.volume = volume;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    //    private AiHandle aiHandle;
    private int type;
    /**
     * 播放唤醒词
     */
    public static final int AWAKE_TYPE = 0;
    /**
     * 播放文本
     */
    public static final int TEXT_TYPE = 1;
    /**
     * 听书
     */
    public static final int BOOK_TYPE = 2;
    public static final int WX_TYPE = 3;
    public static final int NOTICE_TYPE = 4;
    /**
     * 只唤醒一次
     */
    public static final int AWAKE_ONE_TYPE = 5;
    /**
     * 连续唤醒，tts播完自动进入识别状态
     */
    public static final int CONTINIE_TYPE = 6;
    public static final int TIPS_TYPE = 7;
    public static final int AIAUI_TYPE = 8;

    public static final int LANGUAGE_CN_TYPE = 1;
    public static final int LANGUAGE_EN_TYPE = 2;

    public void startTTS(String text, int type) {
        startTTS(text,type,LANGUAGE_CN_TYPE);
    }

    /**
     * 开始播放tts
     * @param text
     * @param type
     * @param language
     */
    public void startTTS(String text, int type,int language) {
        if(TextUtils.isEmpty(text))return;
        state = PLAYING;
        this.type = type;
        this.interrupted = false;
        AiRequest.Builder paramBuilder = AiRequest.builder();
//        paramBuilder.param("vcn", voiceName);
        paramBuilder.param("language", language);


       if(SPUtils.getInstance().getInt(AI_TOGGLE)==1&&language!=2){
            paramBuilder.param("vcn", "xiaofeng");
        }else{
            if(language==1){
                paramBuilder.param("vcn", "yifei");
            }else{
                paramBuilder.param("vcn", "catherine");
            }
        }
//        paramBuilder.param("vcn", "yifei");
//        paramBuilder.param("language", 2);
        paramBuilder.param("pitch", 50);
        paramBuilder.param("volume", volume);
        paramBuilder.param("speed", speed);
        paramBuilder.param("reg", 0);
        paramBuilder.param("rdn", 0);
        paramBuilder.param("textEncoding", "UTF-8");
//paramBuilder.param("pitch", 50);
//        paramBuilder.param("volume", volume);
//        paramBuilder.param("speed", speed);
//paramBuilder.param("reg", 0);
//paramBuilder.param("rdn", 0);
//        paramBuilder.param("textEncoding", $paramValue);
        aiHandle = AiHelper.getInst().start(AbilityConstant.XTTS_ID, paramBuilder.build(), null);
        Log.d(TAG, "TTSHelper startTTS:start.type= " + type);
        if (!aiHandle.isSuccess()) {
            Log.e(TAG, "ERROR::START | handle code:" + aiHandle.getCode());
            return;
        }
        AiRequest.Builder dataBuilder = AiRequest.builder();
//输入文本数据
        AiText textData = AiText
                .get("text")
                .data(text) //text为String类型输入文本
                .valid();
        dataBuilder.payload(textData);
        Log.d(TAG, "TTSHelper startTTS: " + text);
        int ret = AiHelper.getInst().write(dataBuilder.build(), aiHandle);
        Log.d(TAG, "TTSHelper  write.ret=" + ret);
//ret 值为0 写入成功；非0失败，请参照文档中错误码部分排查
        if (ret != 0) {
            String error = "TTSHelper start write failed" + ret;
            Log.e(TAG, error);
        }
    }
    public void setInterrupted(boolean interrupted){
        this.interrupted = interrupted;

    }

    public int getState(){
        return state;
    }

    public boolean isPlaying(){
        return state==PLAYING;
    }

    public void stop() {
        if(state == PLAYING){
            this.interrupted = true;
            endTTS();
        }
    }
    private int state;
    public static final int PLAYING=1;
    public static final int PAUSE=2;
    public static final int END=3;
    public void pause(){
        Log.d(TAG, "pause: ");
        state = PAUSE;
        audioTrack.pause();
    }
    public void resume(){
        Log.d(TAG, "resume: ");
        state = PLAYING;
        audioTrack.play();
    }
    public boolean isEnd(){
        return state==END;
    }
    public void endTTS() {
        Log.d(TAG, "endTTS: state="+state);
        Log.d(TAG, "TTSHelper endTTS: interrupted="+interrupted);
        if(state==END){
            return;
        }
        state=END;
        if (aiHandle != null) {
            int ret = AiHelper.getInst().end(aiHandle);
            Log.d(TAG, "TTSHelper endTTS===: ret="+ret);
            audioTrack.stop();
            cacheArray = null;
            if (ret != 0) {
                String error = "endTTS end failed" + ret;
                Log.e(TAG, error);
            }
        }

        if (onTTSListener != null&&!interrupted) {
            onTTSListener.onTTSFinish(type);
        }
    }

    private byte[] lastArray;
    @Override
    public void onResult(int handleID, List<AiResponse> outputData, Object usrContext) {
        if (outputData == null || outputData.isEmpty()) {
            return;
        }
        if (null != outputData && outputData.size() > 0) {
            for (int i = 0; i < outputData.size(); i++) {
                byte[] bytes = outputData.get(i).getValue();
                if (bytes == null) {
                    continue;
                } else {
                    if (cacheArray == null) {
                        cacheArray = bytes;
                    } else {
                        byte[] resBytes = new byte[(cacheArray != null ? cacheArray.length : 0) + bytes.length];
                        if (cacheArray != null) {
                            System.arraycopy(cacheArray, 0, resBytes, 0, cacheArray.length);
                        }
//                        Log.d(TAG, "onResult: resBytes="+resBytes.length);
                        System.arraycopy(bytes, 0, resBytes, cacheArray != null ? cacheArray.length : 0, bytes.length);
                        cacheArray = resBytes;
                    }
                }
            }
        }
    }

    @Override
    public void onEvent(int handleID, int event, List<AiResponse> eventData, Object usrContext) {
        Log.d(TAG, "onEvent: " + event);
        if (event == AiEvent.EVENT_UNKNOWN.getValue()) {
        }
        if (event == AiEvent.EVENT_START.getValue()) {
            audioTrack.play();
        }
        if (event == AiEvent.EVENT_END.getValue()) {
            audioTrack.write(cacheArray, 0, cacheArray.length);
            if(state!=PAUSE){
                Log.d(TAG, "onEvent: EVENT_END");
                endTTS();
            }

        }
        eventType = event;
        if (event == AiEvent.EVENT_PROGRESS.getValue()) {
            if (cacheArray != null) {
//                Log.d(TAG, "onEvent:EVENT_PROGRESS " + cacheArray.length);
//                if(!Arrays.equals(lastArray,cacheArray)){
//
//                    lastArray = cacheArray;
//                }
//                AudioPlayer player = new AudioPlayer();
//                player.startPlayer();
//                player.play(cacheArray,0, cacheArray.length);
            }
        }
    }

    @Override
    public void onError(int handleID, int err, String msg, Object usrContext) {
        Log.d(TAG, "TTSHelper onError: msg=" + msg);
        if (aiHandle != null) {
            int rets = AiHelper.getInst().end(aiHandle);
            if (rets != 0) {
                String error = "TTSHelper onError end failed" + rets;
                Log.e(TAG, error);
            }
        }
        if (onTTSListener != null) {
            onTTSListener.onError();
        }
    }

    private OnTTSListener onTTSListener;

    public void setOnTTSListener(OnTTSListener onTTSListener) {
        this.onTTSListener = onTTSListener;
    }

    public interface OnTTSListener {
        void onTTSFinish(int type);
        void onError();
    }
}
